# 4 并发控制
- 默认情况下,Shell 命令是串行方式自上而下执行的,但如果有大量的命令需要执行,串行就会浪费大量的时间,这就需要采用并发执行。
# 4.1 利用后台执行实现并发
1 | [root@hdp-1 shell]# cat back_ping.sh |
# 利用管道实现并发控制
- 使用 Linux 管道文件特性制作队列,可以控制并发数量。
- 管道分为命名管道和匿名管道。
- 创建命名管道文件命令是 mkfifo
- 命名管道可跨终端实现数据交换
1 | [root@hdp-1 shell]# cat 255_ping.sh |
# 5 Shell 数组
# 5.1 Shell 数组的基本概念
- 用于区分不同元素的编号称为数组下标。
- 数组的元素有时也称为下标变量。
- 数组分为普通数组和关联数组
- 普通数组中的索引是整数,关联数组的数组索引可以用文本。
- 关联数组使用之前需要声明
- 关联数组由键值对组成。
# 5.1.1 普通数组
- 普通数组中:数组元素的索引(下标)从 0 开始编号,获取数组中的元素要利用索引(下标)。索引(下标)可以是算术表达式,其结果必须是一个整数。
- 普通数组定义。
- 下标从 0 开始
1 | [root@hdp-1 shell]# books=(linux shell awk openstack docker) |
# 5.1.2 关联数组
- 关联数组和普通数组所不同的是,它的索引下标可以是任意的整数和字符串。
- 关联数组定义。eg: info=([name]=tianyun [sex]=male [age]=36 [height]=170 [skill]=cloud)
# 5.1.3 数组声明
- 关联数组需要先声明后使用。
- 通常情况下 Shell 解释器隐式声明普通数组。
- 声明普通数组的方法为:
1 | declare -a array |
- 声明关联数组的方法为:
1 | declare -A array |
# 5.2 Shell 数组的定义
- 在 Linux Shell 中,定义一个数组有多种方法,需要先按照命令规则给数组命名,然后再定义数组的值。数组的定义方法有直接定义数组、下标定义数组、间接定义数组和从文件中读入定义数组,接下来详细介绍定义数组的方法。
# 5.2.1 直接定义数组
- 直接定义数组是用小括号将变量值括起来赋值给数组变量,每个变量值之间要用空隔进行分隔。
1 | [root@hdp-1 shell]# books=(linux shell awk openstack docker) |
# 5.2.2 下标定义数组
- 下标定义数组是用小括号将变量值括起来,同时采用键值对的形式赋值。
1 | array_name=([1]=value1 [2]=value2 [3]=value3 ...) |
- 此种方法为 key-value 键值对的形式,小括号里对应的数字为数组下标,等号后面的内容为下标对应的数组变量的值。
1 | [root@hdp-1 shell]# declare -A info |
# 5.2.3 间接定义数组
- 间接定义数组是分别通过定义数组的方法来定义。其语法格式为:
1 | array_name[0]=value1;array_name[1]=value2;array_name[2]=value3 |
- 此种方法要求一次赋一个值,比较复杂。具体如下所示。
- 间接定义数组。
1 | [root@hdp-1 shell]# array[0]=pear |
# 5.2.4 从文件中读入定义数组
- 从文件中读入定义数组是使用命令的输出结果作为数组的内容。其语法格式为:
1 | array_name=(${命令}) |
- 这种方法要求一次赋多个值。
- 从文件中读入定义数组。
1 | [root@hdp-1 shell]# array=(`cat /etc/passwd`) |
# 5.3 Shell 数组的遍历及赋值
# 5.3.1 常见的访问 Shell 数组表达式
- 表列出了常见访问数组的表达式。
语法 | 描述 |
---|---|
echo $ | 访问数组所有索引 |
echo $ | 访问数组所有索引 |
echo $ | 访问数组所有值 |
echo $ | 访问数组所有值 |
echo $ | 统计数组元素个数 |
echo $ | 访问数组中的第一个元素 |
echo $ | 从数组下标 1 开始 |
echo $ | 从数组下标 1 开始,访问两个元素 |
echo $ | 第 #个元素的字符个数 |
echo $ | 第 0 个元素的字符个数 |
echo $ | 显示第 #个元素 |
echo $ | 显示第 0 个与元素 |
# 5.3.2 while 循环实现 Shell 数组的遍历
- 以 host 文件的每一行作为数组的一个元素来赋值,并对该数组进行遍历。具体如下所示。
- while 循环实现 Shell 数组的遍历。
1 | cat array_host_while.sh |
- while 读入 /etc/hosts 文件的每一行并把它显示出来,hosts [++i]={!hosts [@]} 这个表达式获得数组的索引,${hosts [i]} 这个表达式完成了数组的遍历。
- 执行结果如下:
1 | [root@hdp-1 shell]# ./array_host_while.sh |
# 5.3.3 for 循环实现 Shell 数组的遍历
- 当一个脚本需要传入的参数较多时,可以使用 for 循环进行参数遍历。具体如下例所示。
- for 循环实现 Shell 数组的遍历。
1 | [root@hdp-1 shell]# cat array_host_for.sh |
- 定义一个数组 hosts 以 /etc/hosts 每一行内容作为数组的元素进行遍历。
- 执行结果如下:
1 | [root@hdp-1 shell]# ./array_host_for.sh |
# 6 Shell 函数
# 6.1 Shell 函数的概念
- 函数是由若干条 Shell 命令组成的语句块,实现代码重用和模块化编程,它不是一个单独的进程,不能独立运行,它只是 Shell 程序的一部分。
- Shell 函数和 Shell 程序比较相似,区别在于:Shell 程序在子 Shell 中运行,而 Shell 函数在当前 Shell 中运行,因此在当前 Shell 中,函数可以对 Shell 变量进行修改。
- 函数可以提高程序的可读性和重用性。
# 6.2 Shell 函数的语法
- Shell 函数的语法格式为:
1 | 函数名(){ |
- 关键字 function 表示定义一个函数,可以省略,其后是函数名,两个大括号之间是函数体。创建的函数可以在别的脚本中被调用。
# 6.3 Shell 函数的调用
# 6.3.1 Shell 函数的传参介绍
- 最基本的语法格式为:
1 | 函数名 |
- 带有参数的语法格式为:
1 | 函数名 参数1 参数2 |
- Shell 的位置参数($1、$2、…)可以作为函数的参数来使用。其中,$1 表示第一个参数,$2 表示第二个参数。
- 当 n≥10 时,需要使用 ${n} 来获取参数。例如,获取第十个参数不能用 {10}。
# 6.4 Shell 函数的应用实战
# 6.4.1 脚本中调用 Shell 函数
- 函数必须在使用前需要先被定义。因此,在脚本中使用函数时,必须在脚本开始前定义函数,调用函数仅使用函数名即可
1 | [root@hdp-1 shell]# ./function.sh |
- 接下来使用带有可以传参调用的函数来写一个计算阶乘的脚本
1 | [root@hdp-1 shell]# ./function.sh 5 |
- 函数的位置参数与脚本的位置参数
1 | [root@hdp-1 shell]# ./position_func.sh 2 3 4 |
# 6.4.2 Shell 函数的返回值
- 函数有两种返回值,分别为执行结果的返回值和退出状态码。
- 函数的退出状态码取决于函数中执行的最后一条命令的退出状态码。
- 自定义退出状态码的语法格式为:
1 | return 0 无错误返回 |
- 退出状态码使用 return 保留字返回
- return 的返回值只能是 0~255 的一个整数
- 执行结果的返回值不使用 return
- 执行结果的返回值将保存到变量 “$?” 中
- 函数执行结果的的返回值。
1 | [root@hdp-1 shell]# ./return.sh |
# 6.4.3 Shell 函数数组变量的传参
- 向函数中传递数组
1 | [root@hdp-1 shell]# ./array_func.sh |